/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  algorithm.h
 *        \brief  This is a general-purpose C language algorithm module
 *       \author  Lamdonn
 *        \email  Lamdonn@163.com
 *      \version  1.0.0
 *      \license  GPL2
 *    \copyright  Copyright (C) 2023 Lamdonn.
 ********************************************************************************************************/
#ifndef __algorithm_H
#define __algorithm_H

#include "iterator.h"

/** 
 *  \brief count the number of identical elements in the interval
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] data: address of data
 *  \return count
 */
int alg_count(iterator begin, iterator end, void *data);

/** 
 *  \brief count the number of elements satisfying the condition in the interval
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] pred: function that satisfies the condition of
                    *data: data for comparison
                    return: 0 mismatch condition or !0 match condition
 *  \return count
 */
int alg_count_if(iterator begin, iterator end, int (*pred)(void *data));

/** 
 *  \brief find the container data item that match
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] data: address of data
 *  \return iterator that first match data
 */
iterator alg_find(iterator begin, iterator end, void *data);

/** 
 *  \brief find the container data item that match
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] pred: function that satisfies the condition of
                    *data: data for comparison
                    return: 0 mismatch condition or !0 match condition
 *  \return iterator that first match data
 */
iterator alg_find_if(iterator begin, iterator end, int (*pred)(void *data));

/** 
 *  \brief iterate over each element
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] func: iterate over the callback function
                    it: iterator of the currently traversed data
                    return: none
 *  \return none
 */
void alg_for_each(iterator begin, iterator end, void (*func)(iterator it));

/** 
 *  \brief reverse the specified interval data
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \return 1 success or 0 fail
 */
int alg_reverse(iterator begin, iterator end);

/** 
 *  \brief sort the data in a specified range within a container
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] rule: sorting rule
                    *front: address of front data
                    *back: address of back data
                    return: 0 equal, -1 violate, 1 follow
 *  \return 1 success or 0 fail
 */
int alg_sort(iterator begin, iterator end, int (*rule)(void *front, void *back));

/** 
 *  \brief sort the data by bubble in a specified range within a container
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] rule: sorting rule
                    *front: address of front data
                    *back: address of back data
                    return: 0 equal, -1 violate, 1 follow
 *  \return 1 success or 0 fail
 */
int alg_sort_bubble(iterator begin, iterator end, int (*rule)(void *front, void *back));

/** 
 *  \brief sort the data by select in a specified range within a container
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] rule: sorting rule
                    *front: address of front data
                    *back: address of back data
                    return: 0 equal, -1 violate, 1 follow
 *  \return 1 success or 0 fail
 */
int alg_sort_select(iterator begin, iterator end, int (*rule)(void *front, void *back));

/** 
 *  \brief sort the data by insert in a specified range within a container
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] rule: sorting rule
                    *front: address of front data
                    *back: address of back data
                    return: 0 equal, -1 violate, 1 follow
 *  \return 1 success or 0 fail
 */
int alg_sort_insert(iterator begin, iterator end, int (*rule)(void *front, void *back));

/** 
 *  \brief sort the data by shell in a specified range within a container
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] rule: sorting rule
                    *front: address of front data
                    *back: address of back data
                    return: 0 equal, -1 violate, 1 follow
 *  \return 1 success or 0 fail
 */
int alg_sort_shell(iterator begin, iterator end, int (*rule)(void *front, void *back));

/** 
 *  \brief sort the data by quick in a specified range within a container
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] rule: sorting rule
                    *front: address of front data
                    *back: address of back data
                    return: 0 equal, -1 violate, 1 follow
 *  \return 1 success or 0 fail
 */
int alg_sort_quick(iterator begin, iterator end, int (*rule)(void *front, void *back));

/** 
 *  \brief sort the data by heap in a specified range within a container
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] rule: sorting rule
                    *front: address of front data
                    *back: address of back data
                    return: 0 equal, -1 violate, 1 follow
 *  \return 1 success or 0 fail
 */
int alg_sort_heap(iterator begin, iterator end, int (*rule)(void *front, void *back));

/** 
 *  \brief the specified interval is filled with data for the specified address
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] data: address of data
 *  \return number of successful operations or 0 fail
 */
int alg_fill(iterator begin, iterator end, void *data);

/** 
 *  \brief the n data after the specified starting iterator is populated with data for the specified address
 *  \param[in] begin: interval begin position
 *  \param[in] n: number
 *  \param[in] data: address of data
 *  \return number of successful operations or 0 fail
 */
int alg_fill_n(iterator begin, int n, void *data);

/** 
 *  \brief copy the data of the specified interval to the container indicated by another iterator
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] dest: another iterator
 *  \return number of successful operations or 0 fail
 */
int alg_copy(iterator begin, iterator end, iterator dest);

/** 
 *  \brief remove adjacent duplicate elements
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] cmp: function that satisfies the condition of, default `NULL`
                    *ref: reference data for the container
                    *data: data for comparison
                    return: 0 ref == data, -1 ref < data, 1 ref > data
 *  \return number of successful operations or 0 fail
 */
int alg_unique(iterator begin, iterator end, int (*cmp)(void *ref, void *data));

/** 
 *  \brief replace the specified old data with the new data within the specified interval
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] old: address of old data
 *  \param[in] new: address of new data
 *  \return number of successful operations or 0 fail
 */
int alg_replace(iterator begin, iterator end, void *old, void *new);

/** 
 *  \brief replace the old data that meets the condition with the new data within the specified interval
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] pred: function that satisfies the condition of
                    *data: data for comparison
                    return: 0 mismatch condition or !0 match condition
 *  \param[in] new: address of new data
 *  \return number of successful operations or 0 fail
 */
int alg_replace_if(iterator begin, iterator end, int (*pred)(void *data), void *new);

/** 
 *  \brief remove specified data
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] data: address of data
 *  \return number of successful operations or 0 fail
 */
int alg_remove(iterator begin, iterator end, void *data);

/** 
 *  \brief remove specified data that meets the condition
 *  \param[in] begin: interval begin position
 *  \param[in] end: interval end position
 *  \param[in] pred: function that satisfies the condition of
                    *data: data for comparison
                    return: 0 mismatch condition or !0 match condition
 *  \return number of successful operations or 0 fail
 */
int alg_remove_if(iterator begin, iterator end, int (*pred)(void *data));

/** 
 *  \brief search data for interval 2 in interval 1
 *  \param[in] begin1: interval begin position 1
 *  \param[in] end1: interval end position 1
 *  \param[in] begin2: interval begin position 2
 *  \param[in] end2: interval end position 2
 *  \return iterator for the location search in interval 1
 */
iterator alg_search(iterator begin1, iterator end1, iterator begin2, iterator end2);

#endif 
